package com.zjw.video.custom.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zjw.video.common.entity.FileEntity;
import com.zjw.video.common.mapper.FileMapper;
import com.zjw.video.custom.service.FileService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.UUID;

@Service
public class FileServiceImpl extends ServiceImpl<FileMapper, FileEntity> implements FileService {

    @Value("${file.path}")
    private String basePath;

    @Override
    public FileEntity upload(MultipartFile file, String path) {
        LocalDateTime now = LocalDateTime.now();
        String fileName = UUID.randomUUID().toString().replace("-", "");
        String filePath = basePath + File.separator + path + File.separator;
        String fillFilePath = filePath + fileName;
        File fl = new File(filePath);
        if (!fl.isDirectory() && !fl.mkdirs()) {
            throw new RuntimeException("目录创建失败！");
        }
        try (InputStream inputStream = file.getInputStream(); FileOutputStream fileOutputStream = new FileOutputStream(fillFilePath)) {
            IOUtils.copy(inputStream, fileOutputStream);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        FileEntity fileEntity = new FileEntity();
        fileEntity.setPath(path);
        fileEntity.setFilePath(fillFilePath);
        fileEntity.setName(file.getOriginalFilename());
        fileEntity.setCreatedDatetime(now);
        fileEntity.setUpdatedDatetime(now);
        save(fileEntity);
        return fileEntity;
    }

    @Override
    public void download(String path, String name, HttpServletRequest request, HttpServletResponse response) {
        File file = new File(path);
        try {
            int size = 0;
            String range = request.getHeader("Range");
            long lenStart = 0;
            if (range != null && range.length() > 7) {
                if (range.endsWith("-")) {
                    range = range.substring(6, range.length() - 1);
                    lenStart = Long.parseLong(range);
                    size = 1048576;
                } else {
                    range = range.substring(6, range.length());
                    String[] split = range.split("-");
                    range = split[0];
                    lenStart = Long.parseLong(range);
                    size = (int) (Long.parseLong(split[1]) - lenStart + 1);
                    response.setHeader("Content-Length", size + "");
                    return;
                }
            }

            response.setCharacterEncoding("utf8");
            response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(name, StandardCharsets.UTF_8));
            response.addHeader("Access-Control-Expose-Headers", "Content-disposition");

            response.setHeader("Content-Range", "bytes " + lenStart + "-" + ((file.length() - lenStart - 2 < size) ? file.length() - 1 : lenStart + size - 1) + "/" + file.length());
            response.setHeader("Content-Type", "video/mp4");
            response.setStatus(HttpStatus.PARTIAL_CONTENT.value());//响应码206表示响应内容为部分数据，需要多次请求

            RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
            randomAccessFile.seek(lenStart);//设置读取的开始字节数
            //视频每次返回一兆数据
            byte[] buffer = new byte[size];
            int len = randomAccessFile.read(buffer);
            if (len != -1) {
                response.getOutputStream().write(buffer, 0, len);
            }
            randomAccessFile.close();
            response.getOutputStream().flush();
            response.getOutputStream().close();

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
